package com.fingard.dsp.bank.directbank.pab02.Util.api.ftp.http;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.fingard.dsp.bank.directbank.pab02.Util.api.bean.FileMsgBean;
import com.fingard.dsp.bank.directbank.pab02.Util.api.exception.FtpErrCode;
import com.fingard.dsp.bank.directbank.pab02.Util.api.exception.FtpException;
import com.fingard.dsp.bank.directbank.pab02.Util.api.utils.DataTools;

import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * @date 2018年8月8日上午9:30:31
 * 
 */
public class FtpConnector {
	private final static Log log = LogFactory.getLog(FtpConnector.class);

	private int messLen = 4;
	private String urlStr;
	String headStr = null;

	public FtpConnector(String urlStr) {
		this.urlStr = urlStr;
		log.info("请求的url:" + urlStr);
	}

	public String getUrlStr() {
		return urlStr;
	}

	public void setUrlStr(String urlStr) {
		this.urlStr = urlStr;
	}

	/**
	 * 向url服务器发送请求
	 * 
	 * @param requestData
	 * @return
	 */
	public InputStream sendRequest(byte[] requestData) {
		InputStream is = null;
		OutputStream os = null;
		HttpURLConnection conn = null;
		try {
			URL url = new URL(urlStr);
			conn = (HttpURLConnection) url.openConnection();
			conn.setConnectTimeout(5000);
			conn.setReadTimeout(60000);
			conn.setRequestProperty("Content-Type", "application/xml;charset=UTF-8;");
			conn.setDoOutput(true);
			conn.setDoInput(true);
			os = conn.getOutputStream();
			conn.connect();
			// 发送请求数据
			os.write(requestData);
			os.flush();
			System.out.println("响应码:" + conn.getResponseCode());
			is = conn.getInputStream();
			return is;
		} catch (Exception e) {
			log.error("连接服务器：" + urlStr + " 失败");
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 读取文件传输的消息头
	 * 
	 * @param bean
	 *            文件消息对象，输出结果存放在该对象中返回
	 * @throws FtpException
	 */
	public void readHead(FileMsgBean bean, InputStream input) throws FtpException {
		try {
			byte[] lenByte = new byte[4];
			input.read(lenByte);
			int len = DataTools.getLenth(0, lenByte);
			byte[] head = this.readNum(len, input);

			if (head[0] == '<') {
				headStr = new String(head, "GBK");
			}

			bean.convertXmlToHead(headStr);

		} catch (Exception e) {
			if (e instanceof FtpException) {
				throw (FtpException) e;
			} else
				bean.setFileRetMsg(FtpErrCode.getCodeMsg(FtpErrCode.HttpConnectError));
			throw new FtpException(FtpErrCode.HttpConnectError, e);
		}
	}

	/**
	 * 读取一定长度的输入数据
	 * 
	 * @param num
	 *            输入数据的长度
	 * @return
	 * @throws FtpException
	 */
	private byte[] readNum(int num, InputStream input) throws FtpException {
		// 最大读取请求数据长度1M
		if (num > 1024 * 1024) {
			if (log.isErrorEnabled())
				log.error("请求数据长度过长，length=[" + num + "]");
			throw new FtpException(FtpErrCode.ReadReqLengthError);
		}

		byte[] data = new byte[num];
		int offset = 0;
		int count = -1;
		try {
			while (-1 != (count = input.read(data, offset, num - offset))) {
				offset += count;
				if (offset == num)
					break;
			}
		} catch (IOException e) {
			FtpException fe = new FtpException(FtpErrCode.FileReadError, e);
			throw fe;
		}
		return data;
	}

	/**
	 * 读取文件的某一个分片
	 * 
	 * @param bean
	 *            文件消息对象，输出结果存放在该对象中返回
	 * @throws FtpException
	 */
	public void readCont(FileMsgBean bean, InputStream input) throws FtpException {
		byte[] cont = null;
		int len = this.readInt(input);
		byte[] scrtCont = this.readNum(len, input);

		cont = scrtCont;
		bean.setFileCont(cont);
		bean.setContLen(cont.length);
		if (log.isDebugEnabled())
			log.debug("end read cont");
	}

	/**
	 * 读取int的一个数值，表明后续报文的长度
	 * 
	 * @return 返回后续报文的长度
	 * @throws FtpException
	 */
	private int readInt(InputStream input) throws FtpException {
		StringBuffer sb = new StringBuffer();
		try {
			int ch1 = input.read();
			int ch2 = input.read();
			int ch3 = input.read();
			int ch4 = input.read();
			sb.append((char) ch1);
			sb.append((char) ch2);
			sb.append((char) ch3);
			sb.append((char) ch4);

			if ((ch1 | ch2 | ch3 | ch4) < 0)
				throw new EOFException();
			return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));

		} catch (IOException e) {
			FtpException fe = new FtpException(FtpErrCode.FileReadError, e);
			throw fe;
		}
	}

	/**
	 * bean转xml再转字节数组，再将字节数组头添加4位长度
	 * 
	 * @param bean
	 * @return
	 */
	public byte[] beanToBytes(FileMsgBean bean) {
		byte[] headByte = null;
		try {
			headByte = bean.convertHeadToXml().getBytes("GBK");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (FtpException e) {
			e.printStackTrace();
		}
		byte[] head = DataTools.getLength(4, headByte.length);
		byte[] req = new byte[headByte.length + 4];
		System.arraycopy(head, 0, req, 0, 4);
		System.arraycopy(headByte, 0, req, 4, headByte.length);
		return req;
	}

	/**
	 * 上传文件的bean转字节数组 
	 * 包含头：headByte1，xml转字节数组后头部添加4位长度 
	 * 体：body,文件内容头部添加4位长度
	 * 
	 * @param bean
	 * @return 上传文件的bean转字节数组
	 */
	public byte[] putFileToBytes(FileMsgBean bean) {

		byte[] scrtCont = null;
		int len = 0;

		scrtCont = bean.getFileCont();
		len = bean.getContLen();

		byte[] headByte = null;
		try {
			headByte = bean.convertHeadToXml().getBytes("GBK");
		} catch (UnsupportedEncodingException e1) {
			e1.printStackTrace();
		} catch (FtpException e1) {
			e1.printStackTrace();
		}
		byte[] head = DataTools.getLength(messLen, headByte.length);
		byte[] headByte1 = new byte[headByte.length + messLen];
		System.arraycopy(head, 0, headByte1, 0, messLen);
		System.arraycopy(headByte, 0, headByte1, messLen, headByte.length);

		byte[] bodyHead = DataTools.getLength(messLen, len);
		byte[] body = new byte[len + messLen];
		System.arraycopy(bodyHead, 0, body, 0, messLen);
		System.arraycopy(scrtCont, 0, body, messLen, len);

		ByteArrayOutputStream out = new ByteArrayOutputStream();
		try {
			out.write(headByte1);
			out.write(body);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return out.toByteArray();

	}

}
